{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit Preferences;

interface

uses Classes, SysUtils, {$IFDEF DESIGNER} DesignerPrefs, {$ENDIF} XMLHelper,
     AHMTypes, Logging;

const
  PREFS_FILENAME = 'Preferences.xml';

  // Default values for preferences
  DEF_THEME_NAME = 'tv';
  DEF_LANG_NAME = ''; // Left empty so that native language is used instead
  DEF_FULL_SCREEN = False;
  DEF_HIDE_BORDER = False;
  DEF_MAX_WINDOW = False;
  DEF_SCRN_X_OFFSET = 0.0;
  DEF_SCRN_Y_OFFSET = 0.0;
  DEF_SCRN_X_SCALE = 1.0;
  DEF_SCRN_Y_SCALE = 1.0;
  DEF_VIDEO_THROTTLE = 1;
  DEF_TIME_FORMAT = 'h:nn am/pm';
  DEF_DATE_FORMAT = 'dddd dx mmmm';
  DEF_LOG_LEVEL = INFO;
  DEF_LOG_CACHEING = True;
  DEF_SHOW_DIAG = False;
  DEF_SAVE_CONSOLE_HIST = False;
  DEF_SAVE_GRAPH_TO_FILE = False;
  DEF_KEY_PROFILE_NAME = 'default';
  DEF_MOUSE_CURSOR = mcAuto;
  DEF_MOUSE_RIGHT = mrMenu;
  DEF_SCRN_SAVER_FILE = '';
  DEF_SCRN_SAVER_DELAY = 600;
  DEF_SLIDESHOW_DELAY = 5;
  DEF_USE_PAN_ZOOM = True;
  DEF_USE_FADING = True;
  DEF_SHOW_BORDERS = True;
  DEF_DISPLAY_ADAPTER = 0;
  DEF_DISPLAY_FREQUENCY = 0;
  DEF_TEXTURE_FORMAT = tf32Bit;
  DEF_FONT_QUALITY = fqStandard;
  DEF_VIDEO_RENDERER = vrVMR9;
  DEF_AUDIO_DEVICE = ''; // Left empty so that default audio device is used
  DEF_AUDIO_CAPTURE = ''; // Left empty so that default capture source is used
  DEF_AUDIO_MIXING = amPause;
  DEF_DVD_VIDEO_CODEC = ''; // Left empty so that default filter is used
  DEF_DVD_AUDIO_CODEC = ''; // Left empty so that default filter is used
  DEF_EXTNS_VIDEO = '".AVI",".MPG",".MPEG",".WMV"';
  DEF_EXTNS_AUDIO = '".MP3",".WAV",".CDA",".WMA",".MID",".MIDI"';
  DEF_EXTNS_PLAYLIST = '".ASX",".M3U",".PLS"';
  DEF_REFRESHRATE = 0;
  DEF_SOUNDEFFECTS = True;
  DEF_SOUND_VOLUME = 50; // Sound effect volume range 0..50
  DEF_CHECK_UPDATES = True;
  DEF_GROUP_DIRS = False;
  DEF_HIDE_BALLOON_TIPS = False;
  DEF_VIS_QUALITY = 0;
  DEF_COMPILATION_ARTISTS = False;

type
  TAHMPrefsManager = class
  private
    FThemeName: String;
    FLanguageName: String;
    FDVDVideoFilter: String;
    FDVDAudioFilter: String;
    FAudioDevice: String;
    FAudioCapture: String;
    FAudioMixing: TAHMAudioMixing;
    FDisplayAdapter: Integer;
    FDisplayFrequency: Integer;
    FScreenWidth: Integer;
    FScreenHeight: Integer;
    FScreenRefresh: Integer;
    FScreenXOffset: Single;
    FScreenYOffset: Single;
    FScreenXScale: Single;
    FScreenYScale: Single;
    FVideoThrottle: Integer;
    FFullScreen: Boolean;
    FHideWindowBorder: Boolean;
    FMaximizeWindow: Boolean;
    FDateFormat: String;
    FTimeFormat: String;
    FShowDiagnostics: Boolean;
    FSaveConsoleHistory: Boolean;
    FSaveGraphToFile: Boolean;
    FKeyProfileName: String;
    FTextureFormat: TAHMTextureFormat;
    FFontQuality: TAHMFontQuality;
    FVideoRenderer: TAHMVideoRenderer;
    FMouseCursor: TAHMMouseCursor;
    FMouseRight: TAHMMouseRightAction;
    FScreenSaverFile: String;
    FScreenSaverDelay: Integer;
    FSlideshowDelay: Integer;
    FSlideshowPanZoom: Boolean;
    FSlideshowFading: Boolean;
    FSlideshowBorders: Boolean;
    FSoundEffects: Boolean;
    FSoundVolume: Integer;
    FVideoFormats: String;
    FAudioFormats: String;
    FPlaylistFormats: String;
    FCheckUpdates: Boolean;
    FGroupDirectories: Boolean;
    FHideBalloonTips: Boolean;
    FVisualisationQuality: Integer;
    FCompilationArtists: Boolean;
    FHelper: TAHMXMLHelper;
{$IFDEF DESIGNER}
    FDesignerPrefs: TAHMDesignerPrefsManager;
{$ENDIF}
  protected
    function ParseXML(const Filepath: String): Boolean;
    procedure LogParsingError(const sErrorCode: String);
  public
    constructor Create;
    property ThemeName: String read FThemeName write FThemeName;
    property LanguageName: String read FLanguageName write FLanguageName;
    property DVDVideoFilter: String read FDVDVideoFilter write FDVDVideoFilter;
    property DVDAudioFilter: String read FDVDAudioFilter write FDVDAudioFilter;
    property AudioDevice: String read FAudioDevice write FAudioDevice;
    property AudioCapture: String read FAudioCapture write FAudioCapture;
    property AudioMixing: TAHMAudioMixing read FAudioMixing write FAudioMixing;
    property DisplayFrequency: Integer read FDisplayFrequency write FDisplayFrequency;
    property DisplayAdapter: Integer read FDisplayAdapter write FDisplayAdapter;
    property ScreenWidth: Integer read FScreenWidth write FScreenWidth;
    property ScreenHeight: Integer read FScreenHeight write FScreenHeight;
    property ScreenRefresh: Integer read FScreenRefresh write FScreenRefresh;
    property ScreenXOffset: Single read FScreenXOffset write FScreenXOffset;
    property ScreenYOffset: Single read FScreenYOffset write FScreenYOffset;
    property ScreenXScale: Single read FScreenXScale write FScreenXScale;
    property ScreenYScale: Single read FScreenYScale write FScreenYScale;
    property TextureFormat: TAHMTextureFormat read FTextureFormat write FTextureFormat;
    property FontQuality: TAHMFontQuality read FFontQuality write FFontQuality;
    property VideoRenderer: TAHMVideoRenderer read FVideoRenderer write FVideoRenderer;
    property VideoThrottle: Integer read FVideoThrottle write FVideoThrottle;
    property FullScreen: Boolean read FFullScreen write FFullScreen;
    property HideWindowBorder: Boolean read FHideWindowBorder write FHideWindowBorder;
    property MaximizeWindow: Boolean read FMaximizeWindow write FMaximizeWindow;
    property DateFormat: String read FDateFormat write FDateFormat;
    property TimeFormat: String read FTimeFormat write FTimeFormat;
    property ShowDiagnostics: Boolean read FShowDiagnostics write FShowDiagnostics;
    property SaveConsoleHistory: Boolean read FSaveConsoleHistory write FSaveConsoleHistory;
    property SaveGraphToFile: Boolean read FSaveGraphToFile write FSaveGraphToFile;
    property KeyProfileName: String read FKeyProfileName write FKeyProfileName;
    property MouseCursor: TAHMMouseCursor read FMouseCursor write FMouseCursor;
    property MouseRightAction: TAHMMouseRightAction read FMouseRight write FMouseRight;
    property ScreenSaverFile: String read FScreenSaverFile write FScreenSaverFile;
    property ScreenSaverDelay: Integer read FScreenSaverDelay write FScreenSaverDelay;
    property SlideshowDelay: Integer read FSlideshowDelay write FSlideshowDelay;
    property SlideshowPanZoom: Boolean read FSlideshowPanZoom write FSlideshowPanZoom;
    property SlideshowFading: Boolean read FSlideshowFading write FSlideshowFading;
    property SlideshowBorders: Boolean read FSlideshowBorders write FSlideshowBorders;
    property SoundEffects: Boolean read FSoundEffects write FSoundEffects;
    property SoundVolume: Integer read FSoundVolume write FSoundVolume;
    property VideoFormats: String read FVideoFormats write FVideoFormats;
    property AudioFormats: String read FAudioFormats write FAudioFormats;
    property PlaylistFormats: String read FPlaylistFormats write FPlaylistFormats;
    property CheckUpdates: Boolean read FCheckUpdates write FCheckUpdates;
    property GroupDirectories: Boolean read FGroupDirectories write FGroupDirectories;
    property HideBalloonTips: Boolean read FHideBalloonTips write FHideBalloonTips;
    property VisualisationQuality: Integer read FVisualisationQuality write FVisualisationQuality;
    property CompilationArtists: Boolean read FCompilationArtists write FCompilationArtists;
{$IFDEF DESIGNER}
    property DesignerPrefs: TAHMDesignerPrefsManager read FDesignerPrefs write FDesignerPrefs;
{$ENDIF}
    procedure ResetDefaultPreferences;
    procedure ResetDefaultScreenPosition;
    procedure LoadPreferences;
    procedure SavePreferences;
    procedure SaveAsXML(Lines: TStrings);
  end;

implementation

uses TagNames, XMLTags, ErrorCodes, UIObjects, Screen, ApplicationManager,
     InternetHelper;


constructor TAHMPrefsManager.Create;
begin
  inherited Create;

  // Initialise default preference values
  ResetDefaultPreferences;
end;

procedure TAHMPrefsManager.ResetDefaultPreferences;
begin
  // Set default values for preferences
  FThemeName := DEF_THEME_NAME;
  FLanguageName := DEF_LANG_NAME;
  FDVDVideoFilter := DEF_DVD_VIDEO_CODEC;
  FDVDAudioFilter := DEF_DVD_AUDIO_CODEC;
  FAudioDevice := DEF_AUDIO_DEVICE;
  FAudioCapture := DEF_AUDIO_CAPTURE;
  FAudioMixing := DEF_AUDIO_MIXING;
  FDisplayFrequency := DEF_DISPLAY_FREQUENCY;
  FDisplayAdapter := DEF_DISPLAY_ADAPTER;
  FScreenWidth := DEFAULT_PHYSICAL_WIDTH;
  FScreenHeight := DEFAULT_PHYSICAL_HEIGHT;
  FScreenRefresh := DEF_REFRESHRATE;
  FTextureFormat := DEF_TEXTURE_FORMAT;
  FFontQuality := DEF_FONT_QUALITY;
  FVideoRenderer := DEF_VIDEO_RENDERER;
  FVideoThrottle := DEF_VIDEO_THROTTLE;
  FFullScreen := DEF_FULL_SCREEN;
  FHideWindowBorder := DEF_HIDE_BORDER;
  FMaximizeWindow := DEF_MAX_WINDOW;
  FDateFormat := DEF_DATE_FORMAT;
  FTimeFormat := DEF_TIME_FORMAT;
  FShowDiagnostics := DEF_SHOW_DIAG;
  FSaveConsoleHistory := DEF_SAVE_CONSOLE_HIST;
  FSaveGraphToFile := DEF_SAVE_GRAPH_TO_FILE;
  FKeyProfileName := DEF_KEY_PROFILE_NAME;
  FMouseCursor := DEF_MOUSE_CURSOR;
  FMouseRight := DEF_MOUSE_RIGHT;
  FScreenSaverFile := DEF_SCRN_SAVER_FILE;
  FScreenSaverDelay := DEF_SCRN_SAVER_DELAY;
  FSlideshowDelay := DEF_SLIDESHOW_DELAY;
  FSlideshowPanZoom := DEF_USE_PAN_ZOOM;
  FSlideshowFading := DEF_USE_FADING;
  FSlideshowBorders := DEF_SHOW_BORDERS;
  FSoundEffects := DEF_SOUNDEFFECTS;
  FSoundVolume := DEF_SOUND_VOLUME;
  FVideoFormats := DEF_EXTNS_VIDEO;
  FAudioFormats := DEF_EXTNS_AUDIO;
  FPlaylistFormats := DEF_EXTNS_PLAYLIST;
  FCheckUpdates := DEF_CHECK_UPDATES;
  FGroupDirectories := DEF_GROUP_DIRS;
  FHideBalloonTips := DEF_HIDE_BALLOON_TIPS;
  FVisualisationQuality := DEF_VIS_QUALITY;
  FCompilationArtists := DEF_COMPILATION_ARTISTS;
  LoggingInstance.LoggingLevel := DEF_LOG_LEVEL;
  LoggingInstance.LogFileCacheing := DEF_LOG_CACHEING;

  // Reset screen position & scale too
  ResetDefaultScreenPosition;
end;

procedure TAHMPrefsManager.ResetDefaultScreenPosition;
begin
  // Just reset prefs for screen offset and scale
  FScreenXOffset := DEF_SCRN_X_OFFSET;
  FScreenYOffset := DEF_SCRN_Y_OFFSET;
  FScreenXScale := DEF_SCRN_X_SCALE;
  FScreenYScale := DEF_SCRN_Y_SCALE;
end;

procedure TAHMPrefsManager.LoadPreferences;
var
  Prefs: TStringList;
begin
  // First set default values for prefs
  ResetDefaultPreferences;

  // Parse XML to populate custom preference values
  ParseXML(ApplicationManagerInstance.ConfigPath);

  // Log our preference settings for support purposes
  Prefs := TStringList.Create;
  try
    Prefs.Add('mediate Preference settings are as follows:');
    SaveAsXML(Prefs);
    LogInfo(Prefs);
  finally
    Prefs.Free;
  end;
end;

procedure TAHMPrefsManager.SavePreferences;
var
  Prefs: TStringList;
begin
  Prefs := TStringList.Create;
  try
    SaveAsXML(Prefs);
    Prefs.SaveToFile(ApplicationManagerInstance.ConfigPath + PREFS_FILENAME);
  finally
    Prefs.Free;
  end;
end;

function TAHMPrefsManager.ParseXML(const Filepath: String): Boolean;
var
  RootNode, NextNode: TAHMXMLNode;
begin
  // Default result - problem loading Preferences file
  Result := False;

  // Don't bother trying to parse XML file if its missing
  if not FileExists(FilePath + PREFS_FILENAME) then Exit;

  FHelper := TAHMXMLHelper.Create(Filepath + PREFS_FILENAME);
  try
    // Ignore preamble - we're looking for a ClientPreferences node
    if not FHelper.FindRootElement(RootNode, TAG_PREFERENCES) then
      LogParsingError(XML_PRS_PRF_MISSING_PREFS_START_TAG);

    // What nodes do we have here?
    NextNode := nil;
    while FHelper.NextElement(RootNode, NextNode) do
    begin
      if FHelper.CurrentElement = TAG_THEME_NAME then
        FThemeName := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_LANG_NAME then
        FLanguageName := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_DVD_VIDEO_CODEC then
        FDVDVideoFilter := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_DVD_AUDIO_CODEC then
        FDVDAudioFilter := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_AUDIO_DEVICE then
        FAudioDevice := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_AUDIO_CAPTURE then
        FAudioCapture := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_AUDIO_MIXING then
        FAudioMixing := TAHMAudioMixing(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_DISPLAY_FREQUENCY then
        FDisplayFrequency := StrToIntDef(FHelper.GetValue, FDisplayFrequency)
      else if FHelper.CurrentElement = TAG_DISPLAY_ADAPTER then
        FDisplayAdapter := StrToIntDef(FHelper.GetValue, FDisplayAdapter)
      else if FHelper.CurrentElement = TAG_SCREEN_WIDTH then
        FScreenWidth := StrToIntDef(FHelper.GetValue, FScreenWidth)
      else if FHelper.CurrentElement = TAG_SCREEN_HEIGHT then
        FScreenHeight := StrToIntDef(FHelper.GetValue, FScreenHeight)
      else if FHelper.CurrentElement = TAG_SCREEN_REFRESH then
        FScreenRefresh := StrToIntDef(FHelper.GetValue, FScreenRefresh)
      else if FHelper.CurrentElement = TAG_SCREEN_X_OFFSET then
        FScreenXOffset := StrToIntDef(FHelper.GetValue, 0) / FScreenWidth
      else if FHelper.CurrentElement = TAG_SCREEN_Y_OFFSET then
        FScreenYOffset := StrToIntDef(FHelper.GetValue, 0) / FScreenHeight
      else if FHelper.CurrentElement = TAG_SCREEN_X_SCALED then
        FScreenXScale := StrToIntDef(FHelper.GetValue, FScreenWidth) / FScreenWidth
      else if FHelper.CurrentElement = TAG_SCREEN_Y_SCALED then
        FScreenYScale := StrToIntDef(FHelper.GetValue, FScreenHeight) / FScreenHeight
      else if FHelper.CurrentElement = TAG_TEXTURE_FORMAT then
        FTextureFormat := TAHMTextureFormat(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_FONT_QUALITY then
        FFontQuality := TAHMFontQuality(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_VIDEO_RENDERER then
        FVideoRenderer := TAHMVideoRenderer(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_VIDEO_THROTTLE then
        FVideoThrottle := StrToIntDef(FHelper.GetValue, FVideoThrottle)
      else if FHelper.CurrentElement = TAG_FULL_SCREEN then
        FFullScreen := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_HIDE_BORDER then
        FHideWindowBorder := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_MAX_WINDOW then
        FMaximizeWindow := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_TIME_FORMAT then
        FTimeFormat := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_DATE_FORMAT then
        FDateFormat := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_LOG_LEVEL then
        LoggingInstance.LoggingLevelAsString := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_LOG_CACHEING then
        LoggingInstance.LogFileCacheing := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SHOW_DIAG then
        FShowDiagnostics := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SAVE_CONSOLE_HIST then
        FSaveConsoleHistory := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SAVE_GRAPH_TO_FILE then
        FSaveGraphToFile := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_KEY_PROFILE_NAME then
        FKeyProfileName := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_MOUSE_CURSOR then
        FMouseCursor := TAHMMouseCursor(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_MOUSE_RIGHT then
        FMouseRight := TAHMMouseRightAction(StrToIntDef(FHelper.GetValue, 0))
      else if FHelper.CurrentElement = TAG_SCRN_SAVER_FILE then
        FScreenSaverFile := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_SCRN_SAVER_DELAY then
        FScreenSaverDelay := StrToIntDef(FHelper.GetValue, FScreenSaverDelay)
      else if FHelper.CurrentElement = TAG_SLIDE_SHOW_DELAY then
        FSlideshowDelay := StrToIntDef(FHelper.GetValue, FSlideshowDelay)
      else if FHelper.CurrentElement = TAG_SLIDE_SHOW_PANZOOM then
        FSlideshowPanZoom := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SLIDE_SHOW_FADING then
        FSlideshowFading := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SLIDE_SHOW_BORDERS then
        FSlideshowBorders := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SOUNDEFFECTS then
        FSoundEffects := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_SOUND_VOLUME then
        FSoundVolume := StrToIntDef(FHelper.GetValue, DEF_SOUND_VOLUME)
      else if FHelper.CurrentElement = TAG_EXTNS_VIDEO then
        FVideoFormats := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_EXTNS_AUDIO then
        FAudioFormats := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_EXTNS_PLAYLISTS then
        FPlaylistFormats := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_PROXY_HOST then
        InternetHelperInstance.ProxyServer := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_PROXY_PORT then
        InternetHelperInstance.ProxyPortAsString := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_PROXY_USER then
        InternetHelperInstance.ProxyUsername := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_PROXY_PASS then
        InternetHelperInstance.ProxyPassword := FHelper.GetValue
      else if FHelper.CurrentElement = TAG_CHECK_UPDATES then
        FCheckUpdates := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_GROUP_DIRS then
        FGroupDirectories := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_HIDE_BALLOON_TIPS then
        FHideBalloonTips := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_VIS_QUALITY then
        FVisualisationQuality := StrToIntDef(FHelper.GetValue, FVisualisationQuality)
      else if FHelper.CurrentElement = TAG_COMPILATION_ARTISTS then
        FCompilationArtists := Str2Bool(FHelper.GetValue)
      else if FHelper.CurrentElement = TAG_THEME_SETTINGS then
        ApplicationManagerInstance.ThemeManager.LoadThemeSettings(FHelper)
      else
        LogWarn(XML_PRS_PRF_FOUND_UNKNOWN_CONTENT_TAG);
    end;

    // All is well, parsed preferences file successfully
    Result := True;
  finally
    FHelper.Free;
  end;
end;

procedure TAHMPrefsManager.SaveAsXML(Lines: TStrings);
begin
  Lines.Add(XML_PREAMBLE);
  Lines.Add(BeginTag(TAG_PREFERENCES));

  Lines.Add(TABS[1] + BeginTag(TAG_THEME_NAME) + EncodeXML(FThemeName) + EndTag(TAG_THEME_NAME));
  if FLanguageName <> '' then
    Lines.Add(TABS[1] + BeginTag(TAG_LANG_NAME) + EncodeXML(FLanguageName) + EndTag(TAG_LANG_NAME));
  Lines.Add(TABS[1] + BeginTag(TAG_DVD_VIDEO_CODEC) + EncodeXML(FDVDVideoFilter) + EndTag(TAG_DVD_VIDEO_CODEC));
  Lines.Add(TABS[1] + BeginTag(TAG_DVD_AUDIO_CODEC) + EncodeXML(FDVDAudioFilter) + EndTag(TAG_DVD_AUDIO_CODEC));
  Lines.Add(TABS[1] + BeginTag(TAG_AUDIO_DEVICE) + EncodeXML(FAudioDevice) + EndTag(TAG_AUDIO_DEVICE));
  Lines.Add(TABS[1] + BeginTag(TAG_AUDIO_CAPTURE) + EncodeXML(FAudioCapture) + EndTag(TAG_AUDIO_CAPTURE));
  Lines.Add(TABS[1] + BeginTag(TAG_AUDIO_MIXING) + IntToStr(Ord(FAudioMixing)) + EndTag(TAG_AUDIO_MIXING));
  Lines.Add(TABS[1] + BeginTag(TAG_DISPLAY_FREQUENCY) + IntToStr(FDisplayFrequency) + EndTag(TAG_DISPLAY_FREQUENCY));
  Lines.Add(TABS[1] + BeginTag(TAG_DISPLAY_ADAPTER) + IntToStr(FDisplayAdapter) + EndTag(TAG_DISPLAY_ADAPTER));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_WIDTH) + IntToStr(FScreenWidth) + EndTag(TAG_SCREEN_WIDTH));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_HEIGHT) + IntToStr(FScreenHeight) + EndTag(TAG_SCREEN_HEIGHT));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_REFRESH) + IntToStr(FScreenRefresh) + EndTag(TAG_SCREEN_REFRESH));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_X_OFFSET) + IntToStr(Round(FScreenXOffset*FScreenWidth)) + EndTag(TAG_SCREEN_X_OFFSET));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_Y_OFFSET) + IntToStr(Round(FScreenYOffset*FScreenHeight)) + EndTag(TAG_SCREEN_Y_OFFSET));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_X_SCALED) + IntToStr(Round(FScreenXScale*FScreenWidth)) + EndTag(TAG_SCREEN_X_SCALED));
  Lines.Add(TABS[1] + BeginTag(TAG_SCREEN_Y_SCALED) + IntToStr(Round(FScreenYScale*FScreenHeight)) + EndTag(TAG_SCREEN_Y_SCALED));
  Lines.Add(TABS[1] + BeginTag(TAG_TEXTURE_FORMAT) + IntToStr(Ord(FTextureFormat)) + EndTag(TAG_TEXTURE_FORMAT));
  Lines.Add(TABS[1] + BeginTag(TAG_FONT_QUALITY) + IntToStr(Ord(FFontQuality)) + EndTag(TAG_FONT_QUALITY));
  Lines.Add(TABS[1] + BeginTag(TAG_VIDEO_RENDERER) + IntToStr(Ord(FVideoRenderer)) + EndTag(TAG_VIDEO_RENDERER));
  Lines.Add(TABS[1] + BeginTag(TAG_VIDEO_THROTTLE) + IntToStr(FVideoThrottle) + EndTag(TAG_VIDEO_THROTTLE));
  Lines.Add(TABS[1] + BeginTag(TAG_FULL_SCREEN) + Bool2Str(FFullScreen) + EndTag(TAG_FULL_SCREEN));
  Lines.Add(TABS[1] + BeginTag(TAG_HIDE_BORDER) + Bool2Str(FHideWindowBorder) + EndTag(TAG_HIDE_BORDER));
  Lines.Add(TABS[1] + BeginTag(TAG_MAX_WINDOW) + Bool2Str(FMaximizeWindow) + EndTag(TAG_MAX_WINDOW));
  Lines.Add(TABS[1] + BeginTag(TAG_TIME_FORMAT) + FTimeFormat + EndTag(TAG_TIME_FORMAT));
  Lines.Add(TABS[1] + BeginTag(TAG_DATE_FORMAT) + FDateFormat + EndTag(TAG_DATE_FORMAT));
  Lines.Add(TABS[1] + BeginTag(TAG_LOG_LEVEL) + LoggingInstance.LoggingLevelAsString + EndTag(TAG_LOG_LEVEL));
  Lines.Add(TABS[1] + BeginTag(TAG_LOG_CACHEING) + Bool2Str(LoggingInstance.LogFileCacheing) + EndTag(TAG_LOG_CACHEING));
  Lines.Add(TABS[1] + BeginTag(TAG_SHOW_DIAG) + Bool2Str(FShowDiagnostics) + EndTag(TAG_SHOW_DIAG));
  Lines.Add(TABS[1] + BeginTag(TAG_SAVE_CONSOLE_HIST) + Bool2Str(FSaveConsoleHistory) + EndTag(TAG_SAVE_CONSOLE_HIST));
  Lines.Add(TABS[1] + BeginTag(TAG_SAVE_GRAPH_TO_FILE) + Bool2Str(FSaveGraphToFile) + EndTag(TAG_SAVE_GRAPH_TO_FILE));
  Lines.Add(TABS[1] + BeginTag(TAG_KEY_PROFILE_NAME) + FKeyProfileName + EndTag(TAG_KEY_PROFILE_NAME));
  Lines.Add(TABS[1] + BeginTag(TAG_MOUSE_CURSOR) + IntToStr(Ord(FMouseCursor)) + EndTag(TAG_MOUSE_CURSOR));
  Lines.Add(TABS[1] + BeginTag(TAG_MOUSE_RIGHT) + IntToStr(Ord(FMouseRight)) + EndTag(TAG_MOUSE_RIGHT));
  Lines.Add(TABS[1] + BeginTag(TAG_SCRN_SAVER_FILE) + EncodeXML(FScreenSaverFile) + EndTag(TAG_SCRN_SAVER_FILE));
  Lines.Add(TABS[1] + BeginTag(TAG_SCRN_SAVER_DELAY) + IntToStr(FScreenSaverDelay) + EndTag(TAG_SCRN_SAVER_DELAY));
  Lines.Add(TABS[1] + BeginTag(TAG_SLIDE_SHOW_DELAY) + IntToStr(FSlideshowDelay) + EndTag(TAG_SLIDE_SHOW_DELAY));
  Lines.Add(TABS[1] + BeginTag(TAG_SLIDE_SHOW_PANZOOM) + Bool2Str(FSlideshowPanZoom) + EndTag(TAG_SLIDE_SHOW_PANZOOM));
  Lines.Add(TABS[1] + BeginTag(TAG_SLIDE_SHOW_FADING) + Bool2Str(FSlideshowFading) + EndTag(TAG_SLIDE_SHOW_FADING));
  Lines.Add(TABS[1] + BeginTag(TAG_SLIDE_SHOW_BORDERS) + Bool2Str(FSlideshowBorders) + EndTag(TAG_SLIDE_SHOW_BORDERS));
  Lines.Add(TABS[1] + BeginTag(TAG_SOUNDEFFECTS) + Bool2Str(FSoundEffects) + EndTag(TAG_SOUNDEFFECTS));
  Lines.Add(TABS[1] + BeginTag(TAG_SOUND_VOLUME) + IntToStr(FSoundVolume) + EndTag(TAG_SOUND_VOLUME));
  Lines.Add(TABS[1] + BeginTag(TAG_EXTNS_VIDEO) + FVideoFormats + EndTag(TAG_EXTNS_VIDEO));
  Lines.Add(TABS[1] + BeginTag(TAG_EXTNS_AUDIO) + FAudioFormats + EndTag(TAG_EXTNS_AUDIO));
  Lines.Add(TABS[1] + BeginTag(TAG_EXTNS_PLAYLISTS) + FPlaylistFormats + EndTag(TAG_EXTNS_PLAYLISTS));
  Lines.Add(TABS[1] + BeginTag(TAG_PROXY_HOST) + InternetHelperInstance.ProxyServer + EndTag(TAG_PROXY_HOST));
  Lines.Add(TABS[1] + BeginTag(TAG_PROXY_PORT) + InternetHelperInstance.ProxyPortAsString + EndTag(TAG_PROXY_PORT));
  Lines.Add(TABS[1] + BeginTag(TAG_PROXY_USER) + InternetHelperInstance.ProxyUsername + EndTag(TAG_PROXY_USER));
  Lines.Add(TABS[1] + BeginTag(TAG_PROXY_PASS) + InternetHelperInstance.ProxyPassword + EndTag(TAG_PROXY_PASS));
  Lines.Add(TABS[1] + BeginTag(TAG_CHECK_UPDATES) + Bool2Str(FCheckUpdates) + EndTag(TAG_CHECK_UPDATES));
  Lines.Add(TABS[1] + BeginTag(TAG_GROUP_DIRS) + Bool2Str(FGroupDirectories) + EndTag(TAG_GROUP_DIRS));
  Lines.Add(TABS[1] + BeginTag(TAG_HIDE_BALLOON_TIPS) + Bool2Str(FHideBalloonTips) + EndTag(TAG_HIDE_BALLOON_TIPS));
  Lines.Add(TABS[1] + BeginTag(TAG_VIS_QUALITY) + IntToStr(FVisualisationQuality) + EndTag(TAG_VIS_QUALITY));
  Lines.Add(TABS[1] + BeginTag(TAG_COMPILATION_ARTISTS) + Bool2Str(FCompilationArtists) + EndTag(TAG_COMPILATION_ARTISTS));
  Lines.Add(TABS[1] + BeginTag(TAG_THEME_SETTINGS));
    ApplicationManagerInstance.ThemeManager.SaveThemeSettings(Lines);
  Lines.Add(TABS[1] + EndTag(TAG_THEME_SETTINGS));
  Lines.Add(EndTag(TAG_PREFERENCES));
end;

procedure TAHMPrefsManager.LogParsingError(const sErrorCode: String);
begin
  // Raise exception for global error handler...
  raise EConfigurationException.Create('Encountered error whilst parsing Preferences XML: ' + sErrorCode);
end;

end.
